<script setup lang="tsx">
import { ref } from 'vue'
import { Upload } from '@/components/Upload'
import {
  ElInput,
  ElFormItem,
  ElRow,
  ElButton,
  ElIcon,
  ElTable,
  ElTableColumn,
  ElInputNumber
} from 'element-plus'
import { debounce, isEmpty } from '@/utils/index'
import { cloneDeep } from 'lodash-es'

// 默认的sku字段属性
const defaultColumns = ref([])

// 默认的sku记录值
const defaultSkuItemData = ref({
  img: '',
  money: '',
  purchasing_price: '',
  weight: ''
})

interface SpecItem {
  key: number
  spec_name: string
  valueList: any[] // 这里的 any[] 可能需要根据你的实际需求更改为具体的类型
}

const multiSpecData = ref({
  specList: [] as SpecItem[], // 显式指定 specList 的类型为 SpecItem 数组
  skuList: [],
  // SKU字段
  skuColumns: cloneDeep(defaultColumns),
  // 批量设置sku
  skuBatchForm: defaultSkuItemData
})

// 添加规格组
const handleAddSpecGroup = () => {
  const specList = multiSpecData.value.specList
  specList.push({
    key: specList.length || 0,
    spec_name: '',
    valueList: []
  })
  // 默认规格值
  const groupIndex = specList.length - 1
  handleAddSpecValue(groupIndex)
}

// 添加规格值
const handleAddSpecValue = (groupIndex) => {
  const specGroupItem = multiSpecData.value.specList[groupIndex]
  const specValueList = specGroupItem.valueList
  specValueList.push({
    key: specValueList.length || 0,
    groupKey: specGroupItem.key,
    spec_value: ''
  })
}

// 删除规格组
const handleDeleteSpecGroup = (groupIndex) => {
  multiSpecData.value.specList.splice(groupIndex, 1)
  onUpdate(false)
}

// 删除规格值
const handleDeleteSpecValue = (groupIndex, valueIndex) => {
  multiSpecData.value.specList[groupIndex].valueList.splice(valueIndex, 1)
  onUpdate(false)
}

/**
 * 使用防抖节流方式刷新sku列表
 * @param {boolean} isDebounce 如果true则使用防抖函数
 */
const onUpdate = (isDebounce = true) => {
  if (isDebounce) {
    debounce(getData, 200)()
  } else {
    getData()
  }
}

// 生成并获取多规格数据
const getData = (specList = [], skuList = []) => {
  if (specList.length) {
    multiSpecData.value.specList = cloneDeep(specList)
    multiSpecData.value.skuList = cloneDeep(skuList)
  }
  // 整理所有的规格组
  const groups = getSpecGroupArr()
  // sku记录的规格属性集(生成笛卡尔积)
  const cartesianList = cartesianProductOf(groups)
  // 合并单元格
  const rowSpanArr = getRowSpanArr(groups, cartesianList)
  // 生成sku字段名
  buildSkuColumns(rowSpanArr)
  // 生成sku列表数据
  buildSkuList(cartesianList)
  // 返回多规格数据
  return multiSpecData
}

// 整理所有的规格
const getSpecGroupArr = () => {
  const specGroupArr: any[] = []
  multiSpecData.value.specList.forEach((specGroup) => {
    const itemArr: any[] = []
    specGroup.valueList.forEach((value: any) => {
      itemArr.push(value)
    })
    specGroupArr.push(itemArr)
  })
  return specGroupArr
}

/**
 * 生成笛卡尔积数据
 * cartesianProductOf([arr1, arr2, arr3 ...])
 */
const cartesianProductOf = (arrays) => {
  if (!arrays.length) {
    return []
  }
  return Array.prototype.reduce.call(
    arrays,
    (arr1: any[], arr2: any[]) => {
      const ret: any[] = []
      arr1.forEach((v1) => {
        arr2.forEach((v2) => {
          ret.push(v1.concat([v2]))
        })
      })
      return ret
    },
    [[]]
  )
}

//生成sku表格字段名
const buildSkuColumns = (rowSpanArr) => {
  const specList = multiSpecData.value.specList
  const newColumns = defaultColumns.value.concat()
  // 渲染字段的rowSpan
  const customRender = (specIndex, value, _, index) => {
    const obj = {
      children: value,
      attrs: {}
    }
    const rowSpan = rowSpanArr[specIndex - 1]
    if (index % rowSpan === 0) {
      obj.attrs.rowSpan = rowSpan
    } else {
      obj.attrs.rowSpan = 0
    }
    return obj
  }
  // 遍历规格组整理字段
  for (let specIndex = specList.length; specIndex > 0; specIndex--) {
    const specGroupItem = specList[specIndex - 1]
    newColumns.unshift({
      name: specGroupItem.spec_name,
      dataIndex: `spec_value_${specIndex - 1}`,
      customRender: (value, row, index) => customRender(specIndex, value, row, index)
    })
  }
  multiSpecData.value.skuColumns = newColumns
}

// 生成skuList
const buildSkuList = (cartesianList) => {
  const titles = multiSpecData.value.skuColumns.map((item: any) => item.name)
  // 生成新的skuList
  const newSkuList = []
  for (let i = 0; i < cartesianList.length; i++) {
    const newSkuItem = {
      img: '',
      money: '',
      purchasing_price: '',
      skuKey: cartesianList[i].map((item) => item.key).join('_'),
      weight: '',
      title: ''
      // titleArray: [],
      // specArray: []
    }
    cartesianList[i].forEach((val, idx) => {
      var key = 'id' + titles[idx]
      newSkuItem[key as keyof typeof newSkuItem] = val.spec_value
      // newSkuItem.titleArray.push(val.spec_value)
      // newSkuItem.specArray.push(titles[idx] + '_' + val.spec_value)
      // newSkuItem[`spec_value_${idx}`] = val.spec_value
      newSkuItem[`title`] = val.spec_value
      // newSkuItem.specification = newSkuItem.specArray.join(',')
    })
    newSkuList.push(newSkuItem)
  }
  // 兼容旧的sku数据
  multiSpecData.value.skuList = oldSkuList(newSkuList)
}

// 合并已存在的sku数据
const oldSkuList = (newSkuList) => {
  const oldSkuList = multiSpecData.value.skuList.concat()

  if (!oldSkuList.length || !newSkuList.length) {
    return newSkuList
  }
  for (const index in newSkuList) {
    // 查找符合的旧记录
    let oldSkuItem = {}
    if (oldSkuList.length === newSkuList.length) {
      oldSkuItem = cloneDeep(oldSkuList[index])
    } else {
      oldSkuItem = oldSkuList.find((item) => {
        return item.skuKey == newSkuList[index].skuKey
      })
    }
    // 写入新纪录
    if (oldSkuItem) {
      newSkuList[index] = {
        ...newSkuList[index],
        img: oldSkuItem.img,
        money: oldSkuItem.money,
        purchasing_price: oldSkuItem.purchasing_price,
        weight: oldSkuItem.weight
      }
    }
  }

  return newSkuList
}

// 合并单元格
const getRowSpanArr = (specGroupArr, cartesianList) => {
  const rowSpanArr = []
  var rowSpan = cartesianList.length
  for (let i = 0; i < specGroupArr.length; i++) {
    rowSpanArr[i] = parseInt(rowSpan / specGroupArr[i].length)
    rowSpan = rowSpanArr[i]
  }
  return rowSpanArr
}
//合并表格
const objectSpanMethod = ({ rowIndex, columnIndex }: any) => {
  //拿到第一列要合并的行数
  let specList = multiSpecData.value.specList.filter((e: any) => e.valueList?.length > 0)
  if (columnIndex < specList.length - 1) {
    //列下标小于规格数组长度减一
    let rowSpanNum = 1 //行
    for (let i = columnIndex + 1; i < specList.length; i++) {
      //依次拿到每一列要合并的行数
      rowSpanNum *= specList[i].valueList.length
    }
    if (rowIndex % rowSpanNum === 0) {
      //当条件成立时，即合并行数
      return { rowspan: rowSpanNum, colspan: 1 }
    } else {
      return { rowspan: 0, colspan: 0 }
    }
  }
}
// 规格组输入框change事件
const onChangeSpecGroupIpt = () => {
  onUpdate(true)
}
// 规格值输入框change事件
const onChangeSpecValueIpt = () => {
  onUpdate(true)
}
// 批量设置sku事件
const handleSkuBatch = () => {
  const skuBatchForm = getFilterObject(multiSpecData.value.skuBatchForm)
  const skuList = multiSpecData.value.skuList
  for (const index in skuList) {
    skuList[index] = { ...skuList[index], ...skuBatchForm }
  }
  onUpdate(false)
}

/**
 * 过滤对象的空元素
 * (仅支持一维对象)
 * @param {object} object 源对象
 * @returns {object}
 */
const getFilterObject = (object) => {
  const newObj = {}
  for (const key in object) {
    const value = object[key]
    if (!isEmpty(value)) {
      newObj[key] = value
    }
  }
  return newObj
}
// 获取规格及SKU信息(表单提交)
const getFromSpecData = () => {
  const {
    multiSpecData: { specList, skuList }
  } = this
  const specData = {
    specList: _.cloneDeep(specList),
    skuList: _.cloneDeep(skuList)
  }
  for (const skuIndex in specData.skuList) {
    const skuItem = specData.skuList[skuIndex]
    delete skuItem.image
    // delete skuItem.imageList
    delete skuItem.key
  }
  return specData
}
</script>
<template>
  <div>
    <ElFormItem label="商品规格">
      <div class="box">
        <div class="Specification-header">
          <ElRow class="mb-4">
            <ElButton type="danger" @click="handleAddSpecGroup">+添加规格</ElButton>
          </ElRow>
        </div>
        <div v-for="(item, index) in multiSpecData.specList" :key="index" class="Specification">
          <ElInput
            v-model="item.spec_name"
            placeholder="填写规格"
            style="width: 300px"
            @change="onChangeSpecGroupIpt"
          />
          <ElIcon class="input_icon" @click="handleDeleteSpecGroup(index)" :size="15" color="#ccc">
            <Icon icon="radix-icons:cross-circled" />
          </ElIcon>
          <ElButton style="margin-left: 10px" size="small" @click="handleAddSpecValue(index)">
            添加规格值
          </ElButton>
          <div class="tag">
            <div class="input" v-for="(itm, idx) in item.valueList" :key="idx">
              <ElInput
                placeholder="填写规格值"
                ref="InputRef"
                v-model="itm.spec_value"
                style="width: 100px"
                @change="onChangeSpecValueIpt"
              />
              <ElIcon
                class="icon-CircleClose"
                @click="handleDeleteSpecValue(index, idx)"
                :size="15"
                color="#ccc"
              >
                <Icon icon="radix-icons:cross-circled" />
              </ElIcon>
            </div>
          </div>
        </div>
      </div>
    </ElFormItem>
    <ElFormItem label="sku列表">
      <div class="box-card">
        <!-- 批量设置 -->
        <div v-if="multiSpecData.skuList.length > 1" class="sku-batch">
          <span class="title">批量设置:</span>
          <ElInputNumber
            class="setUp"
            controlsPosition="right"
            v-model="multiSpecData.skuBatchForm.money"
            placeholder="商品售价"
            :min="0"
            :precision="2"
          />
          <ElInputNumber
            class="setUp"
            controlsPosition="right"
            v-model="multiSpecData.skuBatchForm.purchasing_price"
            placeholder="商品进价"
            :min="0"
            :precision="2"
          />
          <ElInputNumber
            class="setUp"
            controlsPosition="right"
            v-model="multiSpecData.skuBatchForm.weight"
            placeholder="商品重量"
            :min="0"
          />
          <ElButton class="setUpButton" @click="handleSkuBatch">立即设置</ElButton>
        </div>
        <ElTable
          :data="multiSpecData.skuList"
          :span-method="objectSpanMethod"
          style="width: 100%"
          border
          :header-style="{ background: '#f0f0f0' }"
        >
          <ElTableColumn
            v-for="(item, index) in multiSpecData.skuColumns"
            :key="index"
            width="100"
            align="center"
            :prop="'id' + item.name"
            :label="item.name"
          />
          <!-- 预览图 -->
          <ElTableColumn prop="img" label="预览图" width="220">
            <template #default="{ row }"><Upload v-model="row.img" /></template>
          </ElTableColumn>
          <!-- 商品价格 -->
          <ElTableColumn prop="money" label="商品售价" width="220">
            <template #default="{ row }">
              <ElInputNumber
                v-model="row.money"
                controlsPosition="right"
                size="small"
                :min="0"
                :precision="2"
              />
            </template>
          </ElTableColumn>
          <ElTableColumn prop="money" label="商品进价" width="220">
            <template #default="{ row }">
              <ElInputNumber
                v-model="row.purchasing_price"
                controlsPosition="right"
                size="small"
                :min="0"
                :precision="2"
              />
            </template>
          </ElTableColumn>
          <!-- 商品重量 -->
          <ElTableColumn prop="weight" label="商品重量" width="220">
            <template #default="{ row }">
              <ElInputNumber v-model="row.weight" controlsPosition="right" size="small" :min="0" />
            </template>
          </ElTableColumn>
        </ElTable>
      </div>
    </ElFormItem>
  </div>
</template>
<style scoped>
.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.Specification {
  position: relative;
  width: 450px;
}

.input_icon {
  position: absolute;
  right: 0;
  z-index: 999;
}

.box-card {
  /* width: 100%; */
  margin-bottom: 20px;
}

.sku-batch {
  margin-bottom: 12px;
  line-height: 40px;
}

.title {
  margin-right: 15px;
  font-size: 13px;
  line-height: 28px;
}

.setUp {
  width: 220px;
  margin-right: 15px;
}

.setUpButton {
  margin-left: 30px;
}

.input {
  position: relative;
  height: 40px;
  margin: 5px;
}

.Specification-header {
  margin: 10px 0;
}

.icon-CircleClose {
  position: absolute;
  left: 90px;
  z-index: 999;
}

.tag {
  display: flex;
  width: 200px;
  height: 50px;
  justify-content: flex-start;
}
</style>
